package Watki;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.FloatControl;

/**
 * Klasa reprezentuje wątek w którym odtwarzane są dźwięki
 * @author lukeh
 * @version 1.0
 */
public class Graj extends Thread
  {

    /**Czy jest pauza?*/
    volatile public boolean paused;
    /**Czy zatrzymano?*/
    volatile public boolean stopped;
    /**Głośność*/
    volatile public FloatControl volume;
    String addr;

    /**
     * Konstruktor ustawiający adres pliku do odegrania
     * @param addr - adres pliku
     */
    public Graj(String addr)
        {
        this.addr = addr;

        }

    /**
     * Odtworzenie pliku
     * <b>Procedura na podstawie dokumentacji JMF</b>
     * Fragmenty zmienione zaznaczone są odpowiednim komentarzem
     * @param fileName adres pliku do oderania
     */
    public void playAudioFile(String fileName)
        {
        File soundFile = new File(fileName);

        try
            {
// Create a stream from the given file.
// Throws IOException or UnsupportedAudioFileException
            AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(soundFile);
// AudioSystem.getAudioInputStream( inputStream ); // alternate audio stream from inputstream
            playAudioStream(audioInputStream);
            } catch (Exception e)
            {
            System.out.println("Problem with file " + fileName + ":");
            e.printStackTrace();
            }
        } // playAudioFile

    /** Plays audio from the given audio input stream. */
    /**
     * Odtwarzanie dźwięku ze strumienia
     * @param audioInputStream
     */
    public void playAudioStream(AudioInputStream audioInputStream)
        {
// Audio format provides information like sample rate, size, channels.
        AudioFormat audioFormat = audioInputStream.getFormat();
        System.out.println("Play input audio format=" + audioFormat);

// Convert compressed audio data to uncompressed PCM format.
        if (audioFormat.getEncoding() != AudioFormat.Encoding.PCM_SIGNED)
            {
// if ((audioFormat.getEncoding() != AudioFormat.Encoding.PCM) ||
// (audioFormat.getEncoding() == AudioFormat.Encoding.ALAW) ||
// (audioFormat.getEncoding() == AudioFormat.Encoding.MP3)) {
            AudioFormat newFormat = new AudioFormat(
                    AudioFormat.Encoding.PCM_SIGNED,
                    audioFormat.getSampleRate(),
                    16,
                    audioFormat.getChannels(),
                    audioFormat.getChannels() * 2,
                    audioFormat.getSampleRate(),
                    false);
            System.out.println("Converting audio format to " + newFormat);
            AudioInputStream newStream = AudioSystem.getAudioInputStream(newFormat, audioInputStream);
            audioFormat = newFormat;
            audioInputStream = newStream;
            }

// Open a data line to play our type of sampled audio.
// Use SourceDataLine for play and TargetDataLine for record.
        DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
        if (!AudioSystem.isLineSupported(info))
            {
            System.out.println("Play.playAudioStream does not handle this type of audio on this system.");
            return;
            }

        try
            {
// Create a SourceDataLine for play back (throws LineUnavailableException).
            SourceDataLine dataLine = (SourceDataLine) AudioSystem.getLine(info);
// System.out.println( "SourceDataLine class=" + dataLine.getClass() );

// The line acquires system resources (throws LineAvailableException).
            dataLine.open(audioFormat);

// Adjust the volume on the output line.
            if (dataLine.isControlSupported(FloatControl.Type.MASTER_GAIN))
                {
                volume = (FloatControl) dataLine.getControl(FloatControl.Type.MASTER_GAIN);
                volume.setValue(100.0F);
                }

// Allows the line to move data in and out to a port.
            dataLine.start();

// Create a buffer for moving data from the audio stream to the line.
            int bufferSize = (int) audioFormat.getSampleRate() * audioFormat.getFrameSize();
            System.out.println(bufferSize);
            byte[] buffer = new byte[bufferSize];

// Move the data until done or there is an error.
            /*******Blok modyfikowany aby reagował na przyciski pauzy i zatrzymania*/
            try
                {
                int bytesRead = 0;
                do
                    {
                    while (!paused && bytesRead >= 0)
                        {
                        bytesRead = audioInputStream.read(buffer, 0, buffer.length);
                        if (bytesRead >= 0)
                            {
                            int framesWritten = dataLine.write(buffer, 0, bytesRead);
                            }
                        } // while
                    } while (paused && !stopped);
                } catch (IOException e)
                {
                e.printStackTrace();
                }
            /*******************************/
            System.out.println("Play.playAudioStream draining line.");
// Continues data line I/O until its buffer is drained.
            dataLine.drain();

            System.out.println("Play.playAudioStream closing line.");
// Closes the data line, freeing any resources such as the audio device.
            dataLine.close();
            } catch (LineUnavailableException e)
            {
            e.printStackTrace();
            }
        } // playAudioStream

    /**
     * Uruchomienie wątku, równoznaczne z odegraniem utworu
     */
    @Override
    public void run()
        {
        playAudioFile(addr);

        }
  }
